#pragma once
#include <vector>
#include <queue>
#include <string>
#include <iostream>
#include "mycond.hpp"
#include "mymutex.hpp"
#include "mypthread.hpp"
#include "mylog.hpp"
using namespace my_pthread;
using namespace my_cond;
using namespace my_mutex;
using namespace my_log;
namespace my_pthreadpool
{
    const int defaultnum = 5;
    template <typename T>
    class mypthreadpool
    {
    private:
    void WakeAll()
    {
        _cond.broadcast();
        LOG(LogLevel::INFO) << "唤醒所有线程";
    }
    void WakeOne()
    {
        _cond.signal();
        LOG(LogLevel::INFO) << "唤醒单个线程";
    }
    // 为了实现单例,我们需要把拷贝构造函数和“=”重载给禁止掉
    mypthreadpool(const mypthreadpool<T> &p) = delete;
    mypthreadpool<T> &operator=(const mypthreadpool<T> &p) = delete;

    public:
    void Start()
    {
        // cout<<"hh1"<<endl;
        if (_isrunning)
        {
            LOG(LogLevel::INFO) << "线程池已经在运行,无法再次运行";
        }
        // cout<<"hh2"<<endl;
        _isrunning = true;
        for (auto &pthread : _pthreads)
        {
            pthread.start();
        }
    }
        mypthreadpool(int num = defaultnum)
            : _num(num), _sleepnum(0), _isrunning(false)
        {
            for (int i = 0; i < _num; i++)
            {
                _pthreads.emplace_back(
                    [this]()
                    {
                        Handler();
                    });
                //cout<<"创建第"<<i+1<<"个线程"<<endl;
                sleep(1);
            }
        }
        static mypthreadpool<T> *GetInstance()
        {
            // cout<<"hh-1"<<endl;
            if (inc == nullptr)
            {
                // 要使用一把新的锁
                _lock.lock();
                LOG(LogLevel::DEBUG) << "开始获取单例...";
                if (inc == nullptr)
                {
                    LOG(LogLevel::DEBUG) << "首次获取单例,开始创建...";
                   // cout << "hh" << endl;
                    inc = new mypthreadpool<T>();
                    //cout << "hh0" << endl;
                    inc->Start();
                }
                _lock.unlock();
            }
            return inc;
        }
        void Join()
        {
            for (auto &pthread : _pthreads)
            {
                pthread.join();
            }
        }
        void Stop()
        {
            if (!_isrunning)
            {
                LOG(LogLevel::INFO) << "线程池已经不在运行,无法再次退出";
                return;
            }
            _isrunning = false;
            WakeAll(); // 把所有线程都唤醒
        }
        bool Equeue(T t)
        {
            if (!_isrunning)
            {
                LOG(LogLevel::INFO) << "线程池已经不在运行,无法加入任务";
                return false;
            }
            _mutex.lock();
            //cout<<"竞争锁成功!"<<endl;
            _task.push(t);
            //cout<<"任务加入成功!"<<endl;
            if (_task.size() == _sleepnum)
            {
                WakeOne();
            }
            _mutex.unlock();
            return true;
        }
        void Handler()
        {
            char name[128];
            pthread_getname_np(pthread_self(), name, sizeof(name));
            while (1)
            {
                T t; // 这个t代表的就是我们的任务
                // 下面这个while循环用来等任务
                _mutex.lock();

                while (_task.empty() && _isrunning)//此时没有任务并且还在运行，就等待
                {
                    _sleepnum++;
                    _cond.wait(_mutex);
                    _sleepnum--;
                }
                if (!_isrunning && _task.empty())
                {
                    LOG(LogLevel::INFO) << name << "线程退出";
                    break; // 退出循环
                }
                // 此时有任务了
                t = _task.front();
                _task.pop();
                _mutex.unlock();
                t(); // 处理任务
                // LOG(LogLevel::DEBUG)<<"pthread name is:"<<name;
                sleep(2);
            }
        }
        ~mypthreadpool()
        {
        }

    private:
        int _num;                         // 线程池的线程个数
        std::vector<mypthread> _pthreads; // 用于储存线程
        std::queue<T> _task;              // 储存任务的队列
        mymutex _mutex;
        mycond _cond;
        Logger _l;       // 日志
        int _sleepnum;   // 休眠的线程数量
        bool _isrunning; // 是否在运行
        // 实现单例
        static mypthreadpool<T> *inc;
        static mymutex _lock;
    };
    // 类内静态对象只可以在类外初始化
    template <typename T>
    mypthreadpool<T> *mypthreadpool<T>::inc = nullptr;
    template <typename T>
    my_mutex::mymutex mypthreadpool<T>::_lock;
}